setTimeout() 和 setInterval()

先来了解一下这两个方法:

1. 定义

setTimeout() 和 setInterval() 都是 HTML DOM window 对象提供的方法

  • setTimeout()
    在指定的延迟时间后调用一个函数或执行一个代码段。
  • setInterval()
    重复调用一个函数或执行一个代码段,在每次调用或执行之间有固定的时间延迟。

2. 语法

  • setTimeout(func, milliseconds)
    setTimeout(code, milliseconds)
  • setInterval(func, milliseconds)
    setInterval(code, milliseconds)

3. 参数

现在来看一下这两个方法的参数具体是怎么设置的。从语法部分可以知道,这两个方法的第二个参数都是时间,单位是毫秒,但是不用带单位;第一个参数都有两种形式,一种是函数,一种是代码段,我们分别来看一下:

3.1 函数

作为这两个方法的参数,这里的函数可以有三种形式:

  1. 函数名 aFunc
    这里的函数名其实是一个具名函数的指针,所以它代表的是一个完整的函数。
  2. 匿名函数 function() {alert"something"};
    匿名函数比较好理解,直接将一个完整的匿名函数作为参数传入,时间到了以后这个匿名函数被执行
  3. 在引号内的函数名和圆括号的组合 "aFunc()"
    不加引号的组合 aFunc(),在传参的过程中,aFunc函数会被执行, 所以,实际上传入的是 aFunc 函数执行完之后的返回值,如果没有设置返回值,则传入 undefined。当时间到了以后,浏览器就只能去执行函数的返回值或 undefined 了。

    但是,当加上引号后,这对组合就变成了字符串。虽然也是函数名之后加圆括号,但是传参的过程中这个函数不会被执行。而当设定的时间到了以后,浏览器却不会简单地拿这个参数当字符串处理,而是会像处理 eval() 中传入的字符串一样,去解析执行引号中的内容。所以跟传入函数名是一样的效果。

    那为什么还要这样传入函数呢,那是因为,这样可以 带参数传入函数。匿名函数还好说,但是当具名函数需要带参数传入的时候,可以采用这种方式,另外一种方式是用一个匿名函数将传参后的函数包裹起来作为这两个方法的第一个参数。

3.2 代码段

并不是将可执行的代码封装成函数以后才能作为这两个方法的参数,一个代码段一样可以传入。

不过这时, 代码段要用引号包含。原理跟以第三种形式传入函数时是一样的,时间到了以后,引号内的代码段会被解析执行。

setTimeout("alert('Hi')", 1000);

上面例子中,一秒钟过后,浏览器会弹出 "Hi"

4. 最佳实践

一般认为,使用超时调用来模拟间歇调用是一种最佳实践。在开发环境中,很少使用真正的间歇调用,因为后一个间歇调用可能会在前一个间歇调用结束前启动。而使用超时调用来模拟就不会出现这种问题。所以最好不要使用间歇调用。

本文参考:

  1. JavaScript Timing Events
  2. WindowTimers.setTimeout()
  3. WindowTimers.setInterval()